package com.cyzy.utils;

import com.cyzy.pojo.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT令牌工具类
 * @author LIGHT
 */
@Component
public class TokenUtils {

    @Value("${jwt.secret:defaultSecret}")
    private String sing;

    @Value("${jwt.expiration:86400000}")
    private long time; // 默认24小时过期
    
    // 存储生成的安全密钥
    private Key key;
    
    // JWT解析器
    private JwtParser jwtParser;
    
    /**
     * 初始化密钥和解析器
     */
    @PostConstruct
    public void init() {
        // 使用Keys.secretKeyFor生成足够强度的密钥
        this.key = Keys.secretKeyFor(SignatureAlgorithm.HS512);
        // 初始化解析器
        this.jwtParser = Jwts.parserBuilder().setSigningKey(key).build();
    }

    /**
     * 生成令牌
     * @param user 用户
     * @return 令牌
     */
    public String generateToken(User user) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getUserId());
        claims.put("username", user.getUserName());
//        claims.put("role",user.getRole());
        return doGenerateToken(claims, user.getUserName());
    }

    /**
     * 从令牌中获取用户名
     * @param token 令牌
     * @return 用户名
     */
    public String getUsernameFromToken(String token) {
        Claims claims = getAllClaimsFromToken(token);
        return claims.getSubject();
    }

    /**
     * 验证令牌
     * @param token 令牌
     * @return 是否有效
     */
    public boolean validateToken(String token) {
        try {
            Claims claims = getAllClaimsFromToken(token);
            return !claims.getExpiration().before(new Date());
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 生成令牌
     * @param claims 声明
     * @param subject 主题
     * @return 令牌
     */
    private String doGenerateToken(Map<String, Object> claims, String subject) {
        Date now = new Date();
        Date expiration = new Date(now.getTime() + time);
        
        return Jwts.builder()
                .setClaims(claims)  // 自定义声明，可以存入额外信息
                .setSubject(subject)  // sub: 用户的唯一标识
                .setIssuedAt(now)  // iat: 签发时间
                .setExpiration(expiration)  // exp: 过期时间
                .signWith(key)  // 使用生成的安全密钥
                .compact();
    }

    /**
     * 从令牌中获取所有声明
     * @param token 令牌
     * @return 声明
     */
    private Claims getAllClaimsFromToken(String token) {
        return jwtParser.parseClaimsJws(token).getBody();
    }
}